package com.jinke.api.modules.app.config;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.google.common.collect.Maps;
import com.jinke.api.common.api.CommonResult;
import com.jinke.api.common.constant.TASMSConstants;
import com.jinke.api.common.constraint.EncryptType;
import com.jinke.api.common.domain.tasms.*;
import com.jinke.api.common.util.OKHttpRetryRequestUtil;
import com.jinke.api.common.util.SHA256Util;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.springframework.stereotype.Component;

import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @projectName:
 * @title: TASMSService
 * @description: 湖南塔澳通信 短信服务
 * @see:
 * @author: hhp
 * @version: 1.0.0
 * @createTime: 2024/8/23 14:50
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class TASMSService {
    private final OKHttpRetryRequestUtil okHttpRetryRequest;

    public TASMSSendSMSResponse sendSMS(TASMSSendSMSDTO sms) {
        TASMSSendSMSResponse tasmsSendSMSResponse = new TASMSSendSMSResponse();
        // 加密字符串
        // 提取字段值
        /*String[] fields = {
                "username=" + sms.getUsername(),
                "nonceStr=" + sms.getNonceStr(),
                "timestamp=" + sms.getTimestamp(),
                "signType=" + sms.getSignType(),
                "spNumber=" + sms.getSpNumber(),
                "content=" + sms.getContent(),
                extractPhones(sms.getPhones())
        };
        String waitEncryptParam = sortAndJoinParameters(fields);*/

        TreeMap<String, Object> paramMap = new TreeMap<>();
        paramMap.put("username", sms.getUsername());
        paramMap.put("nonceStr", sms.getNonceStr());
        paramMap.put("signType", sms.getSignType());
        paramMap.put("timestamp", sms.getTimestamp());
        paramMap.put("spNumber", sms.getSpNumber());
        paramMap.put("content", sms.getContent());
        List<LinkedHashMap<String, Object>> mobileNumbers = new ArrayList<>();
        sms.getPhones().forEach(phone -> {
            LinkedHashMap<String, Object> objectObjectLinkedHashMap = new LinkedHashMap<>();
            objectObjectLinkedHashMap.put("phone", phone.getPhone());
            if (CollectionUtil.isNotEmpty(phone.getVariables())) {
                objectObjectLinkedHashMap.put("variables", phone.getVariables());
            }
            mobileNumbers.add(objectObjectLinkedHashMap);
        });
        paramMap.put("phones", mobileNumbers);
        String waitEncryptParam = toQueryString(paramMap);

        String fullEncryptParam = waitEncryptParam + "&key=" + TASMSConstants.API_KEY;
        String sign = SHA256Util.sha256(fullEncryptParam);
        sms.setSign(sign);
        log.info("fullEncryptParam:[{}], sign:[{}], 请求参数:[{}]", fullEncryptParam, sign, sms);
        Map<String, String> addHeaders = Maps.newHashMap();
        addHeaders.put("Content-Type", "application/json");
        //addHeaders.put("ta-version", "v2");
        Map<String, String> headers = Maps.newHashMap();
        //headers.put("Authorization", getApiToken());
        String responseJson = Optional.ofNullable(
                okHttpRetryRequest.sendPostRequest("taSMS", "application/json", TASMSConstants.SEND_SMS, JSONObject.toJSONString(sms), false, Maps.newHashMap(), addHeaders, headers)
        ).orElse("{}");
        log.info("发送短信响应....[{}]", responseJson);
        TASMSCommonResult tasmsCommonResult = Optional.ofNullable(JSONObject.parseObject(responseJson, TASMSCommonResult.class)).orElse(new TASMSCommonResult());
        if (Optional.ofNullable(tasmsCommonResult.getCode()).orElse("").equals("200")) {
            // 请求成功
            tasmsSendSMSResponse = JSONObject.parseObject(Optional.ofNullable(tasmsCommonResult.getData()).orElse("{}"), TASMSSendSMSResponse.class);
            //响应数据:[TASMSSendSMSResponse(traceId=428510074810535936, msgIds=[TASMSSendSMSResponse.Submitted(phone=8618557516191, msgId=4062C6B68336F8E5205)])]
        }
        return tasmsSendSMSResponse;
    }




    public List<TASMSRecordResponse> smsRecords(TASMSRecordDTO record) {
        List<TASMSRecordResponse> tasmsRecordResponses = Lists.newArrayList();
        String[] fields = {
                "nonceStr=" + record.getNonceStr(),
                "signType=" + record.getSignType(),
                "timestamp=" + record.getTimestamp(),
                "traceId=" + record.getTraceId(),
                "username=" + record.getUsername()
        };
        String waitEncryptParam = sortAndJoinParameters(fields);
        String fullEncryptParam = waitEncryptParam + "&key=" + TASMSConstants.API_KEY;
        String sign = SHA256Util.sha256(fullEncryptParam);
        record.setSign(sign);
        log.info("fullEncryptParam:[{}], sign:[{}], 请求参数:[{}]", fullEncryptParam, sign, record);

        Map<String, String> addHeaders = Maps.newHashMap();
        addHeaders.put("Content-Type", "application/json");
        Map<String, String> headers = Maps.newHashMap();
        //headers.put("Authorization", getApiToken());
        String responseJson = Optional.ofNullable(
                okHttpRetryRequest.sendPostRequest("taSMS", "application/json", TASMSConstants.SMS_RECORDS, JSONObject.toJSONString(record), false, Maps.newHashMap(), addHeaders, headers)
        ).orElse("{}");
        log.info("拿到短信记录结果:[{}]", responseJson);
        TASMSCommonResult tasmsCommonResult = JSONObject.parseObject(responseJson, TASMSCommonResult.class);
        if (Optional.ofNullable(tasmsCommonResult.getCode()).orElse("").equals("200")) {
            // 请求成功
            tasmsRecordResponses = JSON.parseArray(Optional.ofNullable(tasmsCommonResult.getData()).orElse("[]"), TASMSRecordResponse.class);
        }
        return tasmsRecordResponses;
    }

    /**
     * 从 phones 列表中提取 phone 字段值。
     *
     * @param phones phones 列表
     * @return phones 字段值的字符串
     */
    private static String extractPhones(List<TASMSSendSMSDTO.Phone> phones) {
        StringBuilder sb = new StringBuilder();
        sb.append("phones=[");
        phones.forEach(phone -> {
            if (sb.indexOf("}")!= -1) {
                sb.append(",");
            }
            sb.append("{phone=");
            sb.append(phone.getPhone());
            if (CollectionUtil.isNotEmpty(phone.getVariables())) {
                sb.append(", variables=[");
                String collect = String.join(",", phone.getVariables());
                sb.append(collect);
                sb.append("]");
            }
            sb.append("}");
        });
        sb.append("]");
        return sb.toString();
        /*return phones.stream()
                .map(phone -> "phones=[{phone=" + phone.getPhone() +"}]")
                .collect(Collectors.joining(","));*/
    }

    /**
     * 对参数进行排序并以 "&" 符号拼接。
     *
     * @param parameters 参数数组
     * @return 排序后的字符串
     */
    private static String sortAndJoinParameters(String[] parameters) {
        // 使用 TreeSet 自动排序
        Set<String> sortedSet = new TreeSet<>(Arrays.asList(parameters));

        // 使用 Stream API 拼接字符串
        return sortedSet.stream().collect(Collectors.joining("&"));
    }

    private static String toQueryString(TreeMap<String, Object> params) {
        StringBuilder stringBuilder = new StringBuilder();
        params.forEach((key, value) -> {
            // value判空并toString()
            // Value is null and toString()
            String val = Optional.ofNullable(value).orElse("").toString();
            if (!val.isEmpty()) {
                stringBuilder.append(key).append("=").append(val).append("&");
            }
        });
        return stringBuilder.substring(0, stringBuilder.length() - 1);
    }

    public static void main(String[] args) {
        List<TASMSSendSMSDTO.Phone> phones = Lists.newArrayList();
        List<String> variables = Lists.newArrayList();
        variables.add(TASMSConstants.SIGN_NAME);
        variables.add("123456");

        List<String> variables2 = Lists.newArrayList();
        variables2.add(TASMSConstants.SIGN_NAME);
        variables2.add("2222");

        phones.add(new TASMSSendSMSDTO.Phone().setPhone("8613638628989").setVariables(variables));
        phones.add(new TASMSSendSMSDTO.Phone().setPhone("162828364436").setVariables(variables2));

        String s = extractPhones(phones);
        log.info("s:{}", s);

    }

    /**
     * 给手机发验证码
     * @param phoneNum
     * @param verityCode
     * @return
     */
    public  boolean sendSms(String phoneNum, String verityCode) {
        List<TASMSSendSMSDTO.Phone> phones = Lists.newArrayList();
        List<String> variables = Lists.newArrayList();
        // 正式
        //variables.add(TASMSConstants.SIGN_NAME);
        // 测试
        variables.add("TALK2ALL");
        variables.add(verityCode);
        phones.add(new TASMSSendSMSDTO.Phone().setPhone(phoneNum).setVariables(variables));
        TASMSSendSMSDTO tasmsSendSMSDTO = new TASMSSendSMSDTO()
                // 使用变量
                .setContent("【{}】你的验证码是{}")
                .setPhones(phones)
                .setNonceStr(OKHttpRetryRequestUtil.length20nonceStr())
                .setTimestamp(String.valueOf(Instant.now().toEpochMilli()))
                .setSignType(EncryptType.SHA256.name())
                .setSpNumber("106900000000")
                .setUsername(TASMSConstants.CHANNEL_NAME);


        TASMSSendSMSResponse tasmsSendSMSResponse = sendSMS(tasmsSendSMSDTO);
        if (Optional.ofNullable(tasmsSendSMSResponse.getTraceId()).orElse(-1L).equals(-1L)) {
            return false;
        } else {
            return true;
        }


    }

    /**
     * 发固定的广告推广的
     * @param phoneNum
     * @return
     */
    public  boolean sendADSms(String phoneNum) {
        List<TASMSSendSMSDTO.Phone> phones = Lists.newArrayList();

        phones.add(new TASMSSendSMSDTO.Phone().setPhone(phoneNum));
        String ad="dear shipper: \n" +
                "your shippment is on the way, please be aware. \n" +
                "\n" +
                "Dear shipper, your authenication code is .";
         TASMSSendSMSDTO tasmsSendSMSDTO = new TASMSSendSMSDTO()
                // 使用变量
                .setContent(ad)
                .setPhones(phones)
                .setNonceStr(OKHttpRetryRequestUtil.length20nonceStr())
                .setTimestamp(String.valueOf(Instant.now().toEpochMilli()))
                .setSignType(EncryptType.SHA256.name())
                .setSpNumber("106900000000")
                .setUsername(TASMSConstants.CHANNEL_NAME);


        TASMSSendSMSResponse tasmsSendSMSResponse = sendSMS(tasmsSendSMSDTO);
        if (Optional.ofNullable(tasmsSendSMSResponse.getTraceId()).orElse(-1L).equals(-1L)) {
            return false;
        } else {
            return true;
        }


    }
}
